/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package io.netty.channel;

import io.netty.util.Attribute;
import io.netty.util.AttributeKey;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 处理一个 I/O 事件或拦截一个 I/O 操作, 并将其转发到 {@link ChannelPipeline} 中的下一处理器(handler).
 *
 * <h3>子类型</h3>
 * <p>
 * {@link ChannelHandler} 自身没有提供很多方法, 通常您需要实现它的子类之一:
 * <ul>
 * <li>{@link ChannelInboundHandler}: 处理 inbound I/O 事件</li>
 * <li>{@link ChannelOutboundHandler}: 处理 outbound I/O 操作</li>
 * </ul>
 * </p>
 * <p>
 * 另外, 为了方便, 提供了以下适配器类(adapter):
 * <ul>
 * <li>{@link ChannelInboundHandlerAdapter}: 处理 inbound I/O 事件</li>
 * <li>{@link ChannelOutboundHandlerAdapter}: 处理 outbound I/O 操作</li>
 * <li>{@link ChannelDuplexHandler}: 处理 inbound 和 outbound 事件</li>
 * </ul>
 * </p>
 * <p>
 * 更多信息请参阅各个子类的文档.
 * </p>
 *
 * <h3>context 对象</h3>
 * <p>
 * A {@link ChannelHandler} is provided with a {@link ChannelHandlerContext}
 * object.  A {@link ChannelHandler} is supposed to interact with the
 * {@link ChannelPipeline} it belongs to via a context object.  Using the
 * context object, the {@link ChannelHandler} can pass events upstream or
 * downstream, modify the pipeline dynamically, or store the information
 * (using {@link AttributeKey}s) which is specific to the handler.
 *
 * <h3>状态管理t</h3>
 *
 * {@link ChannelHandler} 经常需要存储一些状态信息.
 * 最简单也最推荐的方式是使用成员变量:
 * <pre>
 * public interface Message {
 *     // your methods here
 * }
 *
 * public class DataServerHandler extends {@link SimpleChannelInboundHandler}&lt;Message&gt; {
 *
 *     <b>private boolean loggedIn;</b>
 *
 *     {@code @Override}
 *     public void channelRead0({@link ChannelHandlerContext} ctx, Message message) {
 *         if (message instanceof LoginMessage) {
 *             authenticate((LoginMessage) message);
 *             <b>loggedIn = true;</b>
 *         } else (message instanceof GetDataMessage) {
 *             if (<b>loggedIn</b>) {
 *                 ctx.writeAndFlush(fetchSecret((GetDataMessage) message));
 *             } else {
 *                 fail();
 *             }
 *         }
 *     }
 *     ...
 * }
 * </pre>
 * 因为该 handler 实例有一个转属于某个连接状态变量, 您必须为每个新 channel 创建一个新实例, 以避免竟态条件(未经身份验证的客户端可以获得机密信息):
 * <pre>
 * // Create a new handler instance per channel.
 * // See {@link ChannelInitializer#initChannel(Channel)}.
 * public class DataServerInitializer extends {@link ChannelInitializer}&lt;{@link Channel}&gt; {
 *     {@code @Override}
 *     public void initChannel({@link Channel} channel) {
 *         channel.pipeline().addLast("handler", <b>new DataServerHandler()</b>);
 *     }
 * }
 *
 * </pre>
 *
 * <h4>使用 {@link AttributeKey}s</h4>
 *
 * 虽然推荐使用成员变量来存储一个 handler 的状态, 但出于某种考虑, 您可能不想要创建很多 handler 实例.
 * 在这种情况下, 您可以使用 {@link ChannelHandlerContext} 提供的 {@link AttributeKey}s.
 *
 * <pre>
 * public interface Message {
 *     // your methods here
 * }
 *
 * {@code @Sharable}
 * public class DataServerHandler extends {@link SimpleChannelInboundHandler}&lt;Message&gt; {
 *     private final {@link AttributeKey}&lt;{@link Boolean}&gt; auth =
 *           {@link AttributeKey#valueOf(String) AttributeKey.valueOf("auth")};
 *
 *     {@code @Override}
 *     public void channelRead({@link ChannelHandlerContext} ctx, Message message) {
 *         {@link Attribute}&lt;{@link Boolean}&gt; attr = ctx.attr(auth);
 *         if (message instanceof LoginMessage) {
 *             authenticate((LoginMessage) o);
 *             <b>attr.set(true)</b>;
 *         } else (message instanceof GetDataMessage) {
 *             if (<b>Boolean.TRUE.equals(attr.get())</b>) {
 *                 ctx.writeAndFlush(fetchSecret((GetDataMessage) o));
 *             } else {
 *                 fail();
 *             }
 *         }
 *     }
 *     ...
 * }
 * </pre>
 * 注意, 该 handler 的状态附属于 {@link ChannelHandlerContext}, 您可以将同一 handler 实例添加到不同的 pipelines 中:
 * <pre>
 * public class DataServerInitializer extends {@link ChannelInitializer}&lt;{@link Channel}&gt; {
 *
 *     private static final DataServerHandler <b>SHARED</b> = new DataServerHandler();
 *
 *     {@code @Override}
 *     public void initChannel({@link Channel} channel) {
 *         channel.pipeline().addLast("handler", <b>SHARED</b>);
 *     }
 * }
 * </pre>
 *
 *
 * <h4> {@code @Sharable} 注解</h4>
 * <p>
 * 在上面的使用一个 {@link AttributeKey} 示例中, 您可能已经注意到 {@code @Sharable} 注解.
 * <p>
 * 如果一个 {@link ChannelHandler} 注解有 {@code @Sharable}, 这意味着您可以只创建一个该 handler 实例,
 * 并将它多次添加到一个或多个 {@link ChannelPipeline}s 中, 而不会造成竞争条件.
 * <p>
 * 如果未指定该注解, 每次添加该 handler 到一个 pipeline 中时, 您都需要创建一个新实例, 因为它有不共享的状态(例如成员变量).
 * <p>
 * This annotation is provided for documentation purpose, just like
 * <a href="http://www.javaconcurrencyinpractice.com/annotations/doc/">the JCIP annotations</a>.
 *
 * <h3>Additional resources worth reading</h3>
 * <p>
 * Please refer to the {@link ChannelHandler}, and
 * {@link ChannelPipeline} to find out more about inbound and outbound operations,
 * what fundamental differences they have, how they flow in a  pipeline,  and how to handle
 * the operation in your application.
 */
public interface ChannelHandler {

    /**
     * 当 {@link ChannelHandler} 被添加到实际的 context 并且可以处理事件后, 调用此方法.
     */
    void handlerAdded(ChannelHandlerContext ctx) throws Exception;

    /**
     * 当 {@link ChannelHandler} 被从实际的 context 中移除并且不再处理事件后, 调用此方法.
     */
    void handlerRemoved(ChannelHandlerContext ctx) throws Exception;

    /**
     * 如果抛出一个 {@link Throwable}, 则调用该方法.
     *
     * @deprecated 如果你想要处理该事件, 你应该实现 {@link ChannelInboundHandler}, 并且实现它的那个方法.
     */
    @Deprecated
    void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;

    /**
     * 表示拥有 {@link ChannelHandler} 注解的同一实例可以多次地被添加到一个或多个 {@link ChannelPipeline} 中, 而不会有竞争条件.
     * <p>
     * 如果未指定该注解, 每次将它添加到一个管道时, 您都需要创建一个新 handler 实例, 因为它有不共享的状态, 如成员变量.
     * <p>
     * 提供此注解是出于文档目的, 就像 <a href="http://www.javaconcurrencyinpractice.com/annotations/doc/">JCIP 注解</a>.
     */
    @Inherited
    @Documented
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Sharable {
        // no value
    }
}
